use serde_json::Value;
use std::collections::HashMap;
use std::error::Error;
use std::fs;
use std::fs::File;
use std::io;
// 返回当前周是第几周，当年还剩多少天(不含当天)，距离过年(正月初一)还有多少天。
pub fn time_info(time: &str) -> String {
    let file1 = "iso_weeks.json";
    let file2 = "lunar_new_year_map.json";
    let week_map = read_week_table_from_file(file1);
    let lunar_new_year_map = read_file_to_hashmap_lunar_new_year(file2).unwrap();

    let (y, m, d) = parse_input(time).unwrap();
    let current_day_num = calculate_day_num(y, m, d);
    let week_num = week_map.get(time).unwrap().to_string();
    let days_left = calculate_day_left(y, current_day_num);
    let spring_days_left = calculate_spring_days_left(y, m, d, &lunar_new_year_map);
    format!("{},{},{}", week_num, days_left, spring_days_left)
}

fn read_week_table_from_file(filename: &str) -> HashMap<String, String> {
    let data = fs::read_to_string(filename).expect("Unable to read file");
    let json: HashMap<String, String> = serde_json::from_str(&data).expect("Unable to parse JSON");
    json
}

fn parse_input(time: &str) -> Result<(u32, u32, u32), &'static str> {
    let parts: Vec<&str> = time.split('-').collect();
    if parts.len() != 3 {
        return Err("Invalid input");
    }
    let y: u32 = parts[0].parse().unwrap();
    let m: u32 = parts[1].parse().unwrap();
    let d: u32 = parts[2].parse().unwrap();
    Ok((y, m, d))
}

fn calculate_day_left(y: u32, current_day: u32) -> u32 {
    if is_leap_year(y) {
        366 - current_day
    } else {
        365 - current_day
    }
}

fn calculate_spring_days_left(
    y: u32,
    m: u32,
    d: u32,
    lunar_new_year_map: &HashMap<u32, String>,
) -> u32 {
    // 获取春节日期
    let (spring_month, spring_day) = parse_spring_festival_date(y, lunar_new_year_map)
        .expect("Failed to get spring festival date");

    if m > spring_month || (m == spring_month && d > spring_day) {
        // 当前日期已过当年的春节，计算到下一年春节的天数
        let (next_spring_month, next_spring_day) =
            parse_spring_festival_date(y + 1, lunar_new_year_map)
                .expect("Failed to get next spring festival date");
        calculate_diff_days(y, m, d, y + 1, next_spring_month, next_spring_day)
    } else {
        // 当前日期未到春节，计算到当年春节的天数
        calculate_diff_days(y, m, d, y, spring_month, spring_day)
    }
}
fn parse_spring_festival_date(
    year: u32,
    lunar_new_year_map: &HashMap<u32, String>,
) -> Option<(u32, u32)> {
    // 提取并解析春节日期
    let date = lunar_new_year_map.get(&year)?;
    let parts: Vec<&str> = date.split('-').collect();
    let month = parts[0].parse().ok()?;
    let day = parts[1].parse().ok()?;
    Some((month, day))
}

fn is_leap_year(y: u32) -> bool {
    (y % 4 == 0 && y % 100 != 0) || y % 400 == 0
}

fn match_month_days(y: u32, m: u32) -> Result<u32, &'static str> {
    match m {
        1 | 3 | 5 | 7 | 8 | 10 | 12 => Ok(31),
        4 | 6 | 9 | 11 => Ok(30),
        2 => {
            if is_leap_year(y) {
                Ok(29)
            } else {
                Ok(28)
            }
        }
        _ => Err("Invalid month"),
    }
}

fn calculate_day_num(y: u32, m: u32, d: u32) -> u32 {
    let mut day_num = 0;
    for i in 1..m {
        day_num += match_month_days(y, i).unwrap();
    }
    day_num += d;
    day_num
}
fn calculate_diff_days(
    y: u32,
    m: u32,
    d: u32,
    spring_year: u32,
    spring_month: u32,
    spring_day: u32,
) -> u32 {
    if spring_year > y {
        // 当前年份剩余天数 + 春节所在年的天数
        let current_year_days = if is_leap_year(y) { 366 } else { 365 };
        let current_days_left = current_year_days - calculate_day_num(y, m, d);
        let spring_days_left = calculate_day_num(spring_year, spring_month, spring_day);
        current_days_left + spring_days_left - 1
    } else if spring_year == y {
        // 同年计算两日期之间的差值
        let current_day_num = calculate_day_num(y, m, d);
        let spring_day_num = calculate_day_num(spring_year, spring_month, spring_day);
        spring_day_num - current_day_num - 1
    } else {
        unreachable!();
    }
}
fn read_file_to_hashmap_lunar_new_year(
    file_path: &str,
) -> Result<HashMap<u32, String>, Box<dyn Error>> {
    let file = File::open(file_path)?;
    let reader = io::BufReader::new(file);
    let json: Value = serde_json::from_reader(reader)?;
    let map: HashMap<u32, String> = serde_json::from_value(json)?;
    Ok(map)
}
